fn main() {
    let s = String::from("hello");
    let s1 = s; // s1 is a new variable that owns the value of s
    println!("{}", s1);
    // println!("{}", s); // this line will cause an error because s has already been moved to s1
    let s2 = s1.clone(); // s2 is a new variable that owns a copy of the value of s
    println!("{}", s2);

    let x = 5;
    let y = x; // Copy trait
    println!("{}", y);
    println!("{}", x); // correct output because x has not been moved to y

    let ss = "hello rust";
    let s3 = ss; // Copy trait
    println!("{}", s3);
    println!("{}", ss); 

    let mut s4 = String::from("rust programming");
    borrow_string_mut(&mut s4);
    borrow_string(&s4);

    let s5 = "hello world";
    slice_string(s5);
}

fn borrow_string(s: &String) {
    println!("{}", s);
}

fn borrow_string_mut(s: &mut String) {
    s.push_str(", world!");
    println!("{}", s);
}

// slice
fn slice_string(s: &str) {
    let s1 = &s[0..4];
    println!("{}", s1);
}
